-- promise table
local promise = {
  result = {
    results = {},
    funcs = {},
    _catch = function(_) return error(_) end,
  }
}

promise.start = function(self,func)
  return table.clone(self):initFunc(func)
end

promise.initFunc=function(self,func)
  if table.find(self.result.funcs,func) == nil then
    table.insert(self.result.funcs,func)
  end
  self:run(func,
  {
    resolve = function(...)
      self.result.results = {...}
      self:next(
      self.result.funcs[
      table.find(self.result.funcs,func) + 1
      ]
      )
    end,
    reject = function(errorStatus)
      self.result._catch(errorStatus)
    end
  },
  --arg
  table.unpack(self.result.results)
  ) -- func must running background thread

  return self
end

promise["catch_err"] = function(self,func)
  self.result._catch = func
end

promise.run=function(self,func,...)
  local s,e = pcall(func,...)  
  if s == false then
    self.result._catch(e)
  end
end

promise.next=function(self,func)
  if not func then return self end
  if table.find(self.result.funcs,func) == nil then
    table.insert(self.result.funcs,func)
    return self-- not run now
  end
  self:run(func,
  {
    resolve = function(...)
      self.result.results = {...}
      self:next(
      self.result.funcs[
      table.find(self.result.funcs,func) + 1
      ])
    end,
    reject = function(errorStatus)
      self.result._catch(errorStatus)
    end
  },
  --arg
  table.unpack(self.result.results)
  )-- func must running background thread
  return self
end

return promise
